// 背景
// 有一个软件公司常常用一种不为人知的语言来开发程序，这个语言的特点如下：
// 
// 有两种形式的字符串，一种为加单引号，另一种加双引号。单引号的字符串可以包含双引号，双引号的字符串也可以包含单引号。字符串不能分行，
// 其中也不能包含同样的引号字符。
// 有两种注释方式：@字符为行注释，而双括号(())内的文本为块注释。
// 块注释不能嵌套，所有在块中的文本均被忽略。一个块可以包含几行文本。
// 注释不能出现在字符串内。
// 在块注释中的行注释字符和引号都是没有意义的。
// 注释行中的双括号和引号都是没有意义的。
// 程序的任何部分都不能出现“#”字符；即使在字符串或注释内。
// 分号用来终止语句和生命。每个不在注释或字符串中的分号都被作为程序逻辑行的结束。
// 可以用逻辑行数来粗略地评估程序的大小，即计算不在注释或字符串内的分号的个数。写一个程序读进去几组程序代码，对每组代码都输出逻辑行数和物理行数，
// 并对未终止的注释块和字符串发出警告消息。
// 
// 输入
// 输入包含一个或多个程序，以#表示每个程序终止，以##表示输入终止。
// 
// 输出
// 对于包括未终止字符串的行，输出：“Unterminated string in line n.”，其中n换成行号。
// 
// 如果该程序包括一个未终止的块注释，以如下格式输出一行：”Unterminated block comment at end of program.“
// 
// 在错误信息之后，以如下格式输出一行：”Program x contains y logical lines and z physical lines.“。其中x、y和z用相应的数字代替。


// 1、状态包括四种：'字符串状态、"字符串状态、((注释状态和@注释状态，任何时候最多只有一种状态；
// 2、读到#符号：（1）'字符串状态、"字符串状态中的#代表'字符串状态、"字符串状态结束，输出“Unterminated string in line n.”，n为当前物理行数，
// （2）((注释状态中的#代表((注释状态结束，输出”Unterminated block comment at end of program.“，
// （3）@注释状态中的#代表@注释状态结束，
// （4）#出现在任何位置代表程序结束，输出”Program x contains y logical lines and z physical lines.“，其中x为程序数，y为逻辑行数，z为物理行数，程序数 + 1；
// （5）若前一位字符也为#，代表输入结束；
// 3、读到"符号：不在任何状态下的'代表进入'字符串状态，'字符串状态中的'代表结束'字符串状态；
// 4、读到'符号：不在任何状态下的"代表进入"字符串状态，"字符串状态中的"代表结束"字符串状态；
// 5、读到((符号：不在任何状态下的((代表进入((注释状态；
// 6、读到))符号：((注释状态中的))代表结束((注释状态；
// 7、读到@符号：不在任何状态下的@代表进入@注释状态；
// 8、读到\n符号：（1）除了紧跟#的，所有\n出现，物理行数 + 1，
// （2）@注释状态中的\n代表结束@注释状态，
// （3）'字符串状态、"字符串状态中的\n，结束'字符串状态、"字符串状态，输出“Unterminated string in line n.”，n为当前物理行数；
// 9、读到; 符号：不在任何状态下的; 出现，逻辑行数 + 1；
// 另：“其中也不能包含同样的引号字符。”“注释不能出现在字符串内。”这两句无视就好，考虑会报错

#ifdef _MSC_VER
#define _CRT_SECURE_NO_DEPRECATE
#define inline _inline
#endif

#include <stdio.h>

int main()
{
	int programIndex = 0;
	int logicalLine = 0, physicalLine = 0, allProgramComplete = 0, addPhysicalLine = 0, ssn = 0;
	char now = 0, next = 0;
	while (1)
	{
		addPhysicalLine = 0;//判断是否增加物理行
		if (allProgramComplete)break;
		/*now = getchar();
		next = getchar();	*/
		//int len = strlen(line);
		now = getchar();
		while (now != '\n')
		{
			if (now == '\'')//字符串
			{
				next = getchar();
				int str = 0;//标记是否找到完整的字符串
				while (next != '\n')
				{
					if (next == '\'')
					{
						str = 1; now = getchar(); break;
					}
					if (next == '#')
					{
						printf("Unterminated string in line %d.\n", physicalLine + 1); addPhysicalLine = 1, str = 1;
						printf("Program %d contains %d logical lines and %d physical lines.\n", ++programIndex, logicalLine, physicalLine);
						logicalLine = 0, physicalLine = 0;
						now = next;
						next = getchar();
						if (next == '#')allProgramComplete = 1;
						break;//
					}
					now = next;
					next = getchar();
				}
				if (!str)
				{
					printf("Unterminated string in line %d.\n", physicalLine + 1); break;
				}//
				if (addPhysicalLine)break;
			}
			else if (now == '\"')//字符串
			{
				next = getchar();
				int stringComplete = 0;//标记是否找到完整的字符串
				while (next != '\n')
				{
					if (next == '\"')
					{
						stringComplete = 1; now = getchar(); break;
					}
					if (next == '#')
					{
						printf("Unterminated string in line %d.\n", physicalLine + 1); addPhysicalLine = 1, stringComplete = 1;
						printf("Program %d contains %d logical lines and %d physical lines.\n", ++programIndex, logicalLine, physicalLine);
						logicalLine = 0, physicalLine = 0;
						now = next;
						next = getchar();
						if (next == '#')allProgramComplete = 1;
						break;//
					}
					now = next;
					next = getchar();
				}
				if (!stringComplete)
				{
					printf("Unterminated string in line %d.\n", physicalLine + 1); break;
				}//
				if (addPhysicalLine)break;
			}
			else if (now == '(')
			{//块注释
				next = getchar();
				if (next == '(')
				{
					now = next;
					next = getchar();
					//i += 2;
					int blockEnd = 0;//是否找到））或者遇到#。
					int blockComplete = 0;
					while (!blockEnd)
					{
						while (next != '\n' && !allProgramComplete)
						{
							now = next;
							next = getchar();
							if (now == ')' && next == ')')
							{
								blockEnd = 1; blockComplete = 1;
								now = getchar();
								break;
							}
							if (now == '#' || (now == '\n' && next == '#'))
							{
								printf("Unterminated block comment at end of program.\n");		addPhysicalLine = 1;
								printf("Program %d contains %d logical lines and %d physical lines.\n", ++programIndex, logicalLine, physicalLine);
								logicalLine = 0, physicalLine = 0, blockEnd = 1, blockComplete = 1;
								if (now == '#')ssn = 1;
								if (next == '#')allProgramComplete = 1;
							}
						}
						if (!blockComplete)physicalLine++;
						if (!blockEnd)
						{
							now = next;
							next = getchar();
						}
					}
					if (ssn)break;
				}
				else now = next;
			}
			else if (now == ';')
			{
				logicalLine++;
				now = getchar();
			}
			else if (now == '@')
			{
				now = getchar();
				while (now != '\n')
				{
					now = getchar();
				}
				break;//假如@后面没有#
			}
			else if (now == '#')
			{
				/*if(phc || i!=0)*/printf("Program %d contains %d logical lines and %d physical lines.\n", ++programIndex, logicalLine, physicalLine);
				logicalLine = 0, physicalLine = 0, addPhysicalLine = 1;
				//now = next;
				now = getchar();
				if (now == '#')allProgramComplete = 1;
				while (now != '\n')
				{
					now = getchar();
				}
			}
			else
			{
				now = getchar();
			}
		}
		if (!addPhysicalLine)physicalLine++;
	}
	//system("pause");
	return 0;
}



/*
int main()
{
char now = NULL, next = NULL;
int programIndex = 0;
int logicalLine = 0;
int physicalLine = 0;
BOOL addPhysicalLine = FALSE;
BOOL allProgramComplete = FALSE;

while (TRUE)
{
if (allProgramComplete)
{
break;
}

addPhysicalLine = FALSE;
now = getchar();
switch (now)
{
case '\'': // 单引号字符串
{
break;
}

case '\"':	//双引号字符串
{
break;
}

case '(':	//块注释
{
break;
}

case '@':
break;

case '#':
break;

case '\n':
break;

default:
break;
}
}

End:
return 0;
}
*/

